Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Lint][AMDGPU] No store to const addrspace #109181

Merged
merged 4 commits into from
Sep 25, 2024
Merged

Conversation

jofrn
Copy link
Contributor

@jofrn jofrn commented Sep 18, 2024

Ensure store to const addrspace is not allowed by Linter.

@llvmbot
Copy link
Collaborator

llvmbot commented Sep 18, 2024

@llvm/pr-subscribers-llvm-support
@llvm/pr-subscribers-llvm-analysis
@llvm/pr-subscribers-llvm-ir

@llvm/pr-subscribers-backend-amdgpu

Author: None (jofrn)

Changes

Full diff: https://github.com/llvm/llvm-project/pull/109181.diff

2 Files Affected:

  • (modified) llvm/lib/IR/Verifier.cpp (+17)
  • (added) llvm/test/CodeGen/AMDGPU/const-store.ll (+9)
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index 06a67346fbf959..805c9ef7b72729 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -4224,6 +4224,19 @@ void Verifier::visitLoadInst(LoadInst &LI) {
   visitInstruction(LI);
 }
 
+static bool isConstantAddressSpace(unsigned AS) {
+  switch (AS) {
+    using namespace AMDGPUAS;
+    case CONSTANT_ADDRESS: case CONSTANT_ADDRESS_32BIT:
+    case CONSTANT_BUFFER_0: case CONSTANT_BUFFER_1: case CONSTANT_BUFFER_2: case CONSTANT_BUFFER_3:
+    case CONSTANT_BUFFER_4: case CONSTANT_BUFFER_5: case CONSTANT_BUFFER_6: case CONSTANT_BUFFER_7:
+    case CONSTANT_BUFFER_8: case CONSTANT_BUFFER_9: case CONSTANT_BUFFER_10: case CONSTANT_BUFFER_11:
+    case CONSTANT_BUFFER_12: case CONSTANT_BUFFER_13: case CONSTANT_BUFFER_14: case CONSTANT_BUFFER_15:
+    return true;
+    default: return false;
+  }
+}
+
 void Verifier::visitStoreInst(StoreInst &SI) {
   PointerType *PTy = dyn_cast<PointerType>(SI.getOperand(1)->getType());
   Check(PTy, "Store operand must be a pointer.", &SI);
@@ -4246,6 +4259,10 @@ void Verifier::visitStoreInst(StoreInst &SI) {
     Check(SI.getSyncScopeID() == SyncScope::System,
           "Non-atomic store cannot have SynchronizationScope specified", &SI);
   }
+  if (TT.isAMDGPU()) {
+    Check(!isConstantAddressSpace(SI.getPointerAddressSpace()),
+          "Store cannot be to constant addrspace", &SI);
+  }
   visitInstruction(SI);
 }
 
diff --git a/llvm/test/CodeGen/AMDGPU/const-store.ll b/llvm/test/CodeGen/AMDGPU/const-store.ll
new file mode 100644
index 00000000000000..9447ef9db59986
--- /dev/null
+++ b/llvm/test/CodeGen/AMDGPU/const-store.ll
@@ -0,0 +1,9 @@
+; RUN: not llc -mtriple=amdgcn < %s |& FileCheck %s
+
+define amdgpu_kernel void @store_const(ptr addrspace(4) %out, i32 %a, i32 %b) {
+; CHECK: Store cannot be to constant addrspace
+; CHECK-NEXT: store i32 %r, ptr addrspace(4) %out
+  %r = add i32 %a, %b
+  store i32 %r, ptr addrspace(4) %out
+  ret void
+}

@jofrn jofrn requested a review from shiltian September 18, 2024 19:41
Copy link

github-actions bot commented Sep 18, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

Ensure store to const addrspace is not allowed by IR Verifier.
llvm/test/CodeGen/AMDGPU/const-store.ll Outdated Show resolved Hide resolved
@@ -4224,6 +4224,33 @@ void Verifier::visitLoadInst(LoadInst &LI) {
visitInstruction(LI);
}

static bool isConstantAddressSpace(unsigned AS) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

constant address space is not an AMD only thing. I'm thinking probably we can split this function into target dependent (for example, to query whether an AS is a constant AS) and independent part.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What would the independent part contain if we do not have a use case for it yet?

@jayfoad
Copy link
Contributor

jayfoad commented Sep 19, 2024

Was there any discussion about this? I'm not sure if it should be a verifier error or just undefined behaviour at run time. Also there are other instructions that write to memory, like atomicrmw.

Copy link
Contributor

@arsenm arsenm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This must be UB, and not a verifier error. For example, we allow constant->flat casts. We do not want to have to consider the address spaces involved when folding something like store (addrspacecast ptr addrspace(4) %val to ptr)

@arsenm
Copy link
Contributor

arsenm commented Sep 20, 2024

Plus long term I don't think we should have a constant address space at all.

@jofrn
Copy link
Contributor Author

jofrn commented Sep 20, 2024

Was there any discussion about this? I'm not sure if it should be a verifier error or just undefined behaviour at run time. Also there are other instructions that write to memory, like atomicrmw.

It can be guarded with a flag perhaps. There was discussion to catch this in some way or another since it leads to more confusing error messages later on. Alternatively, we can have these checks go in a separate pass.

@jofrn
Copy link
Contributor Author

jofrn commented Sep 20, 2024

This must be UB, and not a verifier error. For example, we allow constant->flat casts. We do not want to have to consider the address spaces involved when folding something like store (addrspacecast ptr addrspace(4) %val to ptr)

The addrspace in store (addrspacecast ptr addrspace(4) %val to ptr) won't be affected by getPointerAddressSpace since this function asks about the second operand to the store, store i32 %val, ptr addrspace(4) %ptr, in particular, ptr addrspace(4) %ptr. Your example gives a complex expression on the value source, the first operand.

@nikic
Copy link
Contributor

nikic commented Sep 20, 2024

These kinds of checks should go into the Lint pass instead of the Verifier pass.

@arsenm
Copy link
Contributor

arsenm commented Sep 20, 2024

The addrspace in store (addrspacecast ptr addrspace(4) %val to ptr) won't be affected by getPointerAddressSpace since this function asks about the second operand to the store, store i32 %val, ptr addrspace(4) %ptr, in particular, ptr addrspace(4) %ptr. Your example gives a complex expression on the value source, the first operand.

You're reading the example too literally. It should be valid for a pass to strip away the cast, and store directly to the original address space of the pointer without considering any special information. It would be a target specific burden placed on any IR transformation, which is not OK.

This type of check belongs in Lint, which hardly ever gets used and I'm not sure is worth the effort

%r = add i32 %a, %b
store i32 %r, ptr addrspace(4) %out
ret void
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

test atomicrmw, cmpxchg, and a memset, memcpy? Also at least the addrspace(6) case

@@ -0,0 +1,9 @@
; RUN: not opt -mtriple=amdgcn --passes=lint --lint-abort-on-error %s -o - |& FileCheck %s

define amdgpu_kernel void @store_const(ptr addrspace(4) %out, i32 %a, i32 %b) addrspace(4) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no reason to set the address space of the function

@@ -0,0 +1,9 @@
; RUN: not opt -mtriple=amdgcn --passes=lint --lint-abort-on-error %s -o - |& FileCheck %s

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

negative test with a different target

@@ -0,0 +1,9 @@
; RUN: not opt -mtriple=amdgcn --passes=lint --lint-abort-on-error %s -o - |& FileCheck %s
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should move this to test/Analysis/Lint

@jofrn jofrn force-pushed the amdgpu-irverifier branch 2 times, most recently from 0b69206 to b1c3d38 Compare September 20, 2024 19:52
@jofrn jofrn changed the title [Verifier][AMDGPU] No store to const addrspace [Lint][AMDGPU] No store to const addrspace Sep 20, 2024
Copy link
Contributor

@nikic nikic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New approach looks reasonable to me.

if (TT.isAMDGPU()) {
switch(AS) {
using namespace AMDGPUAS;
case CONSTANT_ADDRESS:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be a helper in AMDGPUAddrSpace.h? I'd expect this logic to already exist somewhere, but it looks like AMDGPUAA is only looking for CONSTANT_ADDRESS and nothing else:

if (LI->getPointerAddressSpace() == AMDGPUAS::CONSTANT_ADDRESS)

@@ -401,6 +403,10 @@ void Lint::visitMemoryReference(Instruction &I, const MemoryLocation &Loc,
"Unusual: Address one pointer dereference", &I);

if (Flags & MemRef::Write) {
if (TT.isAMDGPU())
Check(!AMDGPU::isConstantAddressSpace(UnderlyingObject->getType()->getPointerAddressSpace()),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible or better to do the check via TTI? I'm not sure if it's a good idea to do the check based on triple.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This kind of verification doesn't really fit in with TTI

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to be clear, the "check" I meant here was AMDGPU::isConstantAddressSpace.

@@ -401,6 +403,10 @@ void Lint::visitMemoryReference(Instruction &I, const MemoryLocation &Loc,
"Unusual: Address one pointer dereference", &I);

if (Flags & MemRef::Write) {
if (TT.isAMDGPU())
Check(!AMDGPU::isConstantAddressSpace(UnderlyingObject->getType()->getPointerAddressSpace()),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This kind of verification doesn't really fit in with TTI

define amdgpu_kernel void @memcpy_to_const(ptr addrspace(6) %dst, ptr %src) {
; CHECK0: Undefined behavior: Write to memory in const addrspace
; CHECK0-NEXT: call void @llvm.memcpy.p6.p0.i32(ptr addrspace(6) %dst, ptr %src, i32 256, i1 false)
call void @llvm.memcpy.px.py.i32(ptr addrspace(6) %dst, ptr %src, i32 256, i1 false)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use the actual address spaces, not x y

@jofrn jofrn force-pushed the amdgpu-irverifier branch 3 times, most recently from 8fa566a to 251171b Compare September 23, 2024 18:45
Comment on lines +98 to +99
switch (AS) {
using namespace AMDGPUAS;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
switch (AS) {
using namespace AMDGPUAS;
using namespace AMDGPUAS;
switch (AS) {

llvm/test/Analysis/Lint/const-store.ll Show resolved Hide resolved
Copy link
Contributor

@arsenm arsenm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm with nit

llvm/test/Analysis/Lint/const-store.ll Outdated Show resolved Hide resolved
; CHECK0-NEXT: %void = atomicrmw add ptr addrspace(4) %dst, i32 %src acquire
%void = atomicrmw add ptr addrspace(4) %dst, i32 %src acquire
ret void
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe test arbitrary call that may write (those probably should not fail )

@jofrn jofrn merged commit 3e65c30 into llvm:main Sep 25, 2024
8 checks passed
augusto2112 pushed a commit to augusto2112/llvm-project that referenced this pull request Sep 26, 2024
Ensure store to const addrspace is not allowed by Linter.
Sterling-Augustine pushed a commit to Sterling-Augustine/llvm-project that referenced this pull request Sep 27, 2024
Ensure store to const addrspace is not allowed by Linter.
xgupta pushed a commit to xgupta/llvm-project that referenced this pull request Oct 4, 2024
Ensure store to const addrspace is not allowed by Linter.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants